/*
  Copyright (C) 2011, Kyungjoo Kim
  
  This file is part of LINAL (LINear ALgebra)
  
  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Also add information on how to contact you by electronic and paper mail.
  
  
  Kyungjoo Kim
  iamkyungjoo@gmail.com
*/
#include "environment.hxx"

int main(int argc, char **argv) {

  linal::initialize(argc, argv);
  bool help;
  int 
    datatype, cache, nthreads,
    b_mn_host, b_mn_gpu;

  double tol;

  linal::get_option_bool  ("-help", "list options",
                           __FILE__,LINAL_OPTION_MODE_RUN, help);

  linal::get_option_int   ("-datatype", "flaot, double, scomplex, dcomplex",
                           __FILE__,TEST_DATATYPE, datatype, help);
  linal::get_option_int   ("-nthreads", "# of threads",
                           __FILE__,1, nthreads, help);

  linal::get_option_int   ("-b_mn_host", "b_mn for host",
                           __FILE__,10, b_mn_host);

  linal::get_option_int   ("-cache", "cache policy for gpus",
                           __FILE__,0, cache, help);
  linal::get_option_int   ("-b_mn_gpu", "b_mn for gpu",
                           __FILE__,20, b_mn_gpu);

  linal::get_option_double("-tol", "error tolerence",
                           __FILE__,LINAL_ERROR_TOL, tol, help);

  if (help == LINAL_OPTION_MODE_DRY) {
    linal::finalize();
    return 0;
  }

  omp_set_num_threads(nthreads);

  linal::host::Manager_ host;
  linal::gpu::Manager_ gpu[3];

  for (int i=0;i<3;++i)
    gpu[i].set(0, 1, LINAL_DEVICE_GPU);

  host.initialize();

  gpu[0].initialize( 4, cache, 3,  5 );
  gpu[1].initialize( 4, cache, 3, 10 );
  gpu[2].initialize( 4, cache, 3, 20 );

  std::cout << host << std::endl;
  //std::cout << gpu[0] << std::endl;
  
  linal::Dispatcher_ dispatcher;
  dispatcher.add_device( &host );
  dispatcher.add_device( &gpu[0] );
  dispatcher.add_device( &gpu[1] );
  dispatcher.add_device( &gpu[2] );

  linal::Dispatcher_::Group_ grp_host(b_mn_host, 24), grp_gpu(b_mn_gpu, 1);
  dispatcher.add_group( grp_host );
  dispatcher.add_group( grp_gpu );
  
  std::cout << dispatcher << std::endl;

  dispatcher.lock();
  
  std::cout << dispatcher << std::endl;

  dispatcher.reset();
  
  gpu[2].finalize();
  gpu[1].finalize();
  gpu[0].finalize();

  host.finalize();

  linal::finalize();

  return true;
}
